import re
import traceback

from rest_framework import serializers
from rest_framework.serializers import raise_errors_on_nested_writes
from rest_framework.utils import model_meta

from user.models import UserProfile, UserAddress


class UserDetailSerializer(serializers.ModelSerializer):
    """
    用户详细信息
    """

    class Meta:
        model = UserProfile
        fields = '__all__'


class UserSeriallizer(serializers.ModelSerializer):
    """
    使用用户名注册和登陆
    """
    username = serializers.CharField(label='用户名', help_text='用户名', required=True, allow_blank=False)
    captcha_code = serializers.CharField(label='验证码', help_text='验证码', required=True, allow_blank=False)

    class Meta:
        model = UserProfile
        fields = ('username', 'mobile', 'password', 'nickname', 'captcha_code')

    def create(self, validated_data):
        raise_errors_on_nested_writes('create', self, validated_data)
        del validated_data['captcha_code']

        ModelClass = self.Meta.model

        # Remove many-to-many relationships from validated_data.
        # They are not valid arguments to the default `.create()` method,
        # as they require that the instance has already been saved.
        info = model_meta.get_field_info(ModelClass)
        many_to_many = {}
        for field_name, relation_info in info.relations.items():
            if relation_info.to_many and (field_name in validated_data):
                many_to_many[field_name] = validated_data.pop(field_name)

        try:
            instance = ModelClass._default_manager.create(**validated_data)
        except TypeError:
            tb = traceback.format_exc()
            msg = (
                    'Got a `TypeError` when calling `%s.%s.create()`. '
                    'This may be because you have a writable field on the '
                    'serializer class that is not a valid argument to '
                    '`%s.%s.create()`. You may need to make the field '
                    'read-only, or override the %s.create() method to handle '
                    'this correctly.\nOriginal exception was:\n %s' %
                    (
                        ModelClass.__name__,
                        ModelClass._default_manager.name,
                        ModelClass.__name__,
                        ModelClass._default_manager.name,
                        self.__class__.__name__,
                        tb
                    )
            )
            raise TypeError(msg)

        # Save many-to-many relationships after the instance is created.
        if many_to_many:
            for field_name, value in many_to_many.items():
                field = getattr(instance, field_name)
                field.set(value)

        return instance


class SmsSerializer(serializers.ModelSerializer):
    """
    短信序列化
    """
    mobile = serializers.CharField(max_length=11)
    smscode = serializers.CharField(required=False)

    def validate_mobile(self, mobile):
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError("手机号码非法")

        return mobile


class UserAdressSerializer(serializers.ModelSerializer):
    """
    用户地址序列化
    """

    class Meta:
        model = UserAddress
        fields = '__all__'
